package com.wy2cloud.core.security.rsa;

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import com.wy2cloud.core.nio.Charsets;
import com.wy2cloud.core.security.Base64Tools;
import com.wy2cloud.core.security.EnCrypt;
import com.wy2cloud.core.security.EncryptType;
import com.wy2cloud.core.security.SecurityKeyUtils;

public class RSAEncrypt implements EnCrypt {
	
 
    
    
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)  
            throws Exception {  
        if (publicKey == null) {  
            throw new Exception("加密公钥为空, 请设置");  
        }  
        Cipher cipher = null;  
        try {  
            // 使用默认RSA  
            cipher = Cipher.getInstance("RSA");  
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());  
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
            byte[] output = cipher.doFinal(plainTextData);  
            return output;  
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception("无此加密算法");  
        } catch (NoSuchPaddingException e) {  
            e.printStackTrace();  
            return null;  
        } catch (InvalidKeyException e) {  
            throw new Exception("加密公钥非法,请检查");  
        } catch (IllegalBlockSizeException e) {  
            throw new Exception("明文长度非法");  
        } catch (BadPaddingException e) {  
            throw new Exception("明文数据已损坏");  
        }  
    }  
  
    /** 
     * 私钥加密过程 
     *  
     * @param privateKey 
     *            私钥 
     * @param plainTextData 
     *            明文数据 
     * @return 
     * @throws Exception 
     *             加密过程中的异常信息 
     */  
    public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)  
            throws Exception {  
        if (privateKey == null) {  
            throw new Exception("加密私钥为空, 请设置");  
        }  
        Cipher cipher = null;  
        try {  
            // 使用默认RSA  
            cipher = Cipher.getInstance("RSA");  
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);  
            byte[] output = cipher.doFinal(plainTextData);  
            return output;  
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception("无此加密算法");  
        } catch (NoSuchPaddingException e) {  
            e.printStackTrace();  
            return null;  
        } catch (InvalidKeyException e) {  
            throw new Exception("加密私钥非法,请检查");  
        } catch (IllegalBlockSizeException e) {  
            throw new Exception("明文长度非法");  
        } catch (BadPaddingException e) {  
            throw new Exception("明文数据已损坏");  
        }  
    }  
  
    /** 
     * 私钥解密过程 
     *  
     * @param privateKey 
     *            私钥 
     * @param cipherData 
     *            密文数据 
     * @return 明文 
     * @throws Exception 
     *             解密过程中的异常信息 
     */  
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)  
            throws Exception {  
        if (privateKey == null) {  
            throw new Exception("解密私钥为空, 请设置");  
        }  
        Cipher cipher = null;  
        try {  
            // 使用默认RSA  
            cipher = Cipher.getInstance("RSA");  
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());  
            cipher.init(Cipher.DECRYPT_MODE, privateKey);  
            byte[] output = cipher.doFinal(cipherData);  
            return output;  
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception("无此解密算法");  
        } catch (NoSuchPaddingException e) {  
            e.printStackTrace();  
            return null;  
        } catch (InvalidKeyException e) {  
            throw new Exception("解密私钥非法,请检查");  
        } catch (IllegalBlockSizeException e) {  
            throw new Exception("密文长度非法");  
        } catch (BadPaddingException e) {  
            throw new Exception("密文数据已损坏");  
        }  
    }  
  
    /** 
     * 公钥解密过程 
     *  
     * @param publicKey 
     *            公钥 
     * @param cipherData 
     *            密文数据 
     * @return 明文 
     * @throws Exception 
     *             解密过程中的异常信息 
     */  
    public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)  
            throws Exception {  
        if (publicKey == null) {  
            throw new Exception("解密公钥为空, 请设置");  
        }  
        Cipher cipher = null;  
        try {  
            // 使用默认RSA  
            cipher = Cipher.getInstance("RSA");  
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());  
            cipher.init(Cipher.DECRYPT_MODE, publicKey);  
            byte[] output = cipher.doFinal(cipherData);  
            return output;  
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception("无此解密算法");  
        } catch (NoSuchPaddingException e) {  
            e.printStackTrace();  
            return null;  
        } catch (InvalidKeyException e) {  
            throw new Exception("解密公钥非法,请检查");  
        } catch (IllegalBlockSizeException e) {  
            throw new Exception("密文长度非法");  
        } catch (BadPaddingException e) {  
            throw new Exception("密文数据已损坏");  
        }  
    }  
    
    

	private final RSAEncryptTypeByKey rsaEncryptTypeByKey;
	
	private RSAPublicKey publicKey;
	private RSAPrivateKey privateKey;
	
	
	
	
	
	public RSAEncryptTypeByKey getRsaEncryptTypeByKey() {
		return rsaEncryptTypeByKey;
	}
	public RSAPublicKey getPublicKey() {
		return publicKey;
	}
	public RSAPrivateKey getPrivateKey() {
		return privateKey;
	}
	
	
	public RSAEncrypt(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
		super();
		this.rsaEncryptTypeByKey = RSAEncryptTypeByKey.PrivateEncrypt;
		this.publicKey = publicKey;
		this.privateKey = privateKey;
	}

	public RSAEncrypt(RSAEncryptTypeByKey rsaEncryptTypeByKey, RSAPublicKey publicKey, RSAPrivateKey privateKey) {
		super();
		this.rsaEncryptTypeByKey = rsaEncryptTypeByKey;
		this.publicKey = publicKey;
		this.privateKey = privateKey;
	}

	@Override
	public byte[] encode(byte[] src)  throws Exception {
		if(this.rsaEncryptTypeByKey==RSAEncryptTypeByKey.PrivateEncrypt) {
			return encrypt(privateKey, src);
		}else {
			return encrypt(publicKey, src);
		}
	}

	@Override
	public byte[] decode(byte[] src)  throws Exception {
		if(this.rsaEncryptTypeByKey==RSAEncryptTypeByKey.PrivateEncrypt) {
			return decrypt(publicKey, src);
		}else {
			return decrypt(privateKey, src);
		}
	}

    public String encode(String srcStr) throws Exception{
	    return encode(srcStr, Charsets.UTF8);
    }
	public String encode(String srcStr,String charsetName) throws Exception {
	    byte[] enBytes=encode(srcStr.getBytes(charsetName));
	    return  Base64Tools.encode(enBytes,charsetName);
    }
    public String decode(String enStr) throws Exception{
	    return decode(enStr,Charsets.UTF8);
    }
    public String decode(String enStr,String charsetName) throws Exception {
	    byte[] enBytes=Base64Tools.decode(enStr,charsetName);
	    return new String(decode(enBytes),charsetName);
    }



	public static  void  main(String... args) throws Exception {
        KeyPair keyPair = SecurityKeyUtils.generatorKeyPair(EncryptType.RSA_1024);
        System.out.println("public:"+ Base64Tools.encode(keyPair.getPublic().getEncoded()));
        System.out.println("private:"+Base64Tools.encode(keyPair.getPrivate().getEncoded()));


        RSAEncrypt rsaEncrypt=new RSAEncrypt(RSAEncryptTypeByKey.PublicEncrypt,(RSAPublicKey) keyPair.getPublic(),(RSAPrivateKey) keyPair.getPrivate());

        String src="day day up!s";
        System.out.println(src);
        byte[] srcBytes=src.getBytes(Charsets.UTF8);
        byte[] encryBytes=rsaEncrypt.encode(srcBytes);
        String encryStr=Base64Tools.encode(encryBytes);
        System.out.println("encryStr:"+encryStr);
        byte[] decodeBytes=rsaEncrypt.decode(encryBytes);
        String decodeStr=new String(decodeBytes);
        System.out.println(decodeStr);

        String enstr= rsaEncrypt.encode(src,Charsets.UTF8);
        System.out.println("enstr:"+enstr);
        String destr=rsaEncrypt.decode(enstr,Charsets.UTF8);
        System.out.println(destr);
    }


}
